﻿using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestByWire.Test.EmulatedTutorials
{
    [TestClass]
    public class Repetitions : TestTarget<Repeater>
    {
        [TestMethod]
        public void DefaultToForever()
        {
            Given.That<IValueFetcher>(x => x.GetValue()).Returns(3); // Repeated forever

            var total = When.Calling.Iterate(5);

            Assert.AreEqual(15, total);
        }

        [TestMethod]
        public void SubsequentCallsReiteratesStack()
        {
            Given.That<IValueFetcher>(x => x.GetValue()).Returns(1); // Repeated once
            Given.That<IValueFetcher>(x => x.GetValue()).Returns(3); // Repeated forever

            var total = When.Calling.Iterate(5);

            Assert.AreEqual(13, total);
        }

        [TestMethod]
        public void ExplicitRepeatsArePreserved()
        {
            Given.That<IValueFetcher>(x => x.GetValue()).Returns(1); // Repeated once
            Given.That<IValueFetcher>(x => x.GetValue()).Returns(3).Repeat(2); // Repeated once
            Given.That<IValueFetcher>(x => x.GetValue()).Returns(5); // Repeated forever

            var total = When.Calling.Iterate(5);

            Assert.AreEqual(17, total);
        }

        [TestMethod]
        public void AHasSameSematicsAsGiven()
        {
            Scenario.Is(BuildIteration);

            var total = When.Calling.Iterate(5);

            Assert.AreEqual(17, total);
        }

        [TestMethod]
        public void GivenHasPrecedensOverA()
        {
            Scenario.Is(BuildIteration);

            Given.That<IValueFetcher>(x => x.GetValue()).Returns(5);

            var total = When.Calling.Iterate(5);

            Assert.AreEqual(25, total);
        }

        private static void BuildIteration()
        {
            A.CallTo<IValueFetcher>(x => x.GetValue()).Returns(1); // Repeated once
            A.CallTo<IValueFetcher>(x => x.GetValue()).Returns(3).Repeat(2); // Repeated once
            A.CallTo<IValueFetcher>(x => x.GetValue()).Returns(5); // Repeated forever

        }
    }

    public class Repeater
    {
        private readonly IValueFetcher _fetcher;

        public Repeater(IValueFetcher fetcher)
        {
            _fetcher = fetcher;
        }

        public int Iterate(int times)
        {
            int outVal = 0;
            for (int i = 0; i < times; i++)
                outVal += _fetcher.GetValue();
            return outVal;
        }
    }

    public interface IValueFetcher
    {
        int GetValue();
    }
}

